home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
130 MIDI Tool Box
/
130 MIDI Tool Box.iso
/
bytemidi
/
rxint11.a
< prev
Wrap
Text File
|
1979-12-31
|
13KB
|
376 lines
; RXINT:
; version 1.1
; 2/2/86
;
; This is the main receive interrupt.
; It is called when the DART receives data.
; This version supports carry-over (running) status bytes
; as well as a translate table.
;
DSEG
; These are C's globals
PUBLIC r_segment_
PUBLIC ptr_
PUBLIC end_
PUBLIC destbyte_
PUBLIC clsb_
PUBLIC cmsb_
PUBLIC stop_
PUBLIC LAST_STAT_
PUBLIC C_O_F_ ; status carry-over flag
PUBLIC clk_type_ ; 0=internal, 1=external
PUBLIC counter_dec_
PUBLIC in_filt_ ; the MIDI input filter
; bit:
; 0 = Note on filt
; 1 = Note off filt
; 2 = Prog change filt
; 3 = Channel after-touch
; 4 = Pitch wheel
; 5 = All other controllers
; 6 = Key after-touch
CSEG ; ALL CODE
PUBLIC rxint_
rxint_:
STI ; interrupts back on
PUSH AX
MOV AL,0B9H ; shut off counter interrupt
OUT 021H,AL
PUSH BX
PUSH DX
PUSH ES
PUSH DS
MOV AX,0 ; this will be new value for the
; DS so we can access the OLD DS
MOV DS,AX
MOV BX,WORD [04FAH] ; put new DS in BX
MOV DS,BX ; put new DS in DS
MOV AX,r_segment_
MOV ES,AX ; set buffer segment
sst:
MOV DX,0FFA2H ; midi stat
MOV AL,1 ; rd register 1
OUT DX,AL
IN AL,DX ; RD reg 1
AND AL,32 ; Rx overrun error?
JNZ finished ; if so, than we're REALLY done!
_st: ; jumped to by _iret if another char is available
IN AL,DX ; read status register
AND AL,1 ; Rx char?
JZ _iret ; if not, return
MOV DX,0FFA0H ; MIDI data
IN AL,DX ; now let's read it
MOV DL,AL ; store in DL for later
CMP AL,0F8H ; timing clock?
JNZ C1 ; if not, check for stop
MOV DL,counter_dec_ ; get amount to decrement counter
MOV DH,0 ; we'll do a word subtract
MOV AL,clsb_ ; get lsb
MOV AH,cmsb_ ; get msb
SUB AX,DX ; dcr word
MOV clsb_,AL ; store lsb
MOV cmsb_,AH ; store msb
JMP _iret ; if is, all done
C1:
CMP AL,0FCH ; MIDI Stop?
JNZ C4 ; if not, continue
MOV BYTE stop_,1 ; else, set stop byte
JMP _iret ; and return
C4:
AND AL,0F0H ; strip off top 4
CMP AL,0F0H ; running status?
JZ _iret ; if so, we're done
MOV BYTE AL,destbyte_ ; get destbyte
CMP AL,0FFH ; shall we continue?
JZ _iret ; if not, then we're done
MOV BL,AL ; keep for later
AND AL,0F0H ; strip off top four
JZ _newmsg ; first byte of a new message - What a revelation!
contzz: ; branch point from carry-over status
CMP AL,010H ; Note ON?
JZ _nton ; yes?
CMP AL,020H ; Note OFF?
JZ _noff ; yes?
CMP AL,070H ; Poly key pres?
JZ _keypres
CMP AL,040H ; Bender?
JZ _bender ; yes?
CMP AL,050H ; Control Change?
JZ _cchan ; yes?
CMP AL,060H ; Channel Velocity?
JZ _cvel ; For now, throw away channel velocity
CMP AL,030H ; Prog Change?
JZ _pchan ; yes?
JMP _iret ; This would fall through for FILTed out codes
; this routine (newmsg) processes the first byte of a given
; message, and also decides if it is an important message
_newmsg: ; it's a new message
MOV AL,DL ; retrieve
AND AL,080H
MOV AL,DL
MOV BYTE C_O_F_,0 ; no carry-over
JNZ contxx ; check for MIDI carry-over stat.
MOV BYTE AL,LAST_STAT_ ; get previous status byte
MOV BYTE C_O_F_,0FFH ; carry-over status
contxx:
MOV BYTE destbyte_,0 ; this is default in case code isn't
; supported or is filtered out
MOV CL,in_filt_ ; this is input filter
AND AL,0F0H ; strip off channel info.
MOV LAST_STAT_,AL ; save new last stat
CMP AL,090H ; Note ON?
JZ _nnon ; yes?
CMP AL,080H ; Note OFF?
JZ _nnoff ; yes?
CMP AL,0A0H ; Poly key press?
JZ _nkeypres ; yes?
CMP AL,0E0H ; Pitch Wheel
JZ _npwch ; yes?
CMP AL,0B0H ; Control Change?
JZ _ncchan ; yes?
CMP AL,0C0H ; Prog. Chan?
JZ _npchan ; yes?
CMP AL,0D0H ; Channel Velocity?
JZ _nchanv ; yes?
JMP _iret ; otherwise, it must be a code we don't support
_nnon: ; first byte of a note on just came in
AND CL,1 ; keep note-ons?
JZ _iret ; no, then all done.
CALL _stime ; store present time
MOV BYTE ES:[BX],0 ; put 0 at *ptr - I.D. code for note on/off
MOV BYTE destbyte_,011H ; note on in dest byte
JMP _cco ; check carry-over
_nnoff: ; first byte of note off just came in
AND CL,2 ; keep note-offs?
JZ _iret ; no, then all done
CALL _stime ; same as _nnon (above)
MOV BYTE ES:[BX],0 ; I.D.
MOV BYTE destbyte_,021H ; note off in destbyte
JMP _cco ; check carry-over
_ncchan: ; first byte of control change
AND CL,32 ; keep control changes?
JZ _iret ; no
CALL _stime
MOV BYTE ES:[BX],0C0H ; I.D.
MOV BYTE destbyte_,051H ; cchan in destbyte
JMP _cco ; check carry-over
_npchan: ; 1st byte of program change
AND CL,4 ; keep prog. changes?
JZ _iret
CALL _stime
MOV BYTE ES:[BX],040H ; I.D.
MOV BYTE destbyte_,031H ; prog chan in destbyte
JMP _cco ; check carry-over
_nchanv: ; 1st byte of Channel pressure
AND CL,8 ; keep channel pressure?
JZ _iret
CALL _stime
MOV BYTE ES:[BX],041H ; I.D.
MOV BYTE destbyte_,061H ; chan vel in dbyte
JMP _cco ; check carry-over
_nkeypres: ; 1st byte of Poly. key pres.
AND CL,64 ; keep poly. key pres?
JZ _iret
CALL _stime
MOV BYTE ES:[BX],060H ; I.D.
MOV BYTE destbyte_,071H ; chan vel in dbyte
JMP _cco ; check carry-over
_npwch: ; first byte of pitch wheel change
AND CL,16 ; keep pitch wheel?
JZ _iret
CALL _stime
MOV BYTE ES:[BX],080H ; I.D.
MOV BYTE destbyte_,041H ; pitch wheel in dbyte
JMP _cco ; check carry-over
_cco: ; check carry over flag
MOV BYTE AL,C_O_F_ ; get carry over flag
OR AL,AL ; set flags
JZ _iret
MOV BYTE AL,destbyte_
MOV BL,AL
AND AL,0F0H
JMP contzz ; carry over
; now for the routines that are called while a message is in
; progress:
_nton: ; note on processing routine
AND BL,1 ; BL still has destbyte in it
MOV WORD BX,ptr_ ; get pointer
JZ _ntonvel ; must be a 2, so go and save velocity
OR DL,080H ; set top bit of note
ADD BX,3 ; inr pointer to note
MOV BYTE ES:[BX],DL ; store it
INC BYTE destbyte_ ; inr for velocity, which will come in next
JMP _iret ; all done
_ntonvel: ; must be a velocity byte
SHR DL,1 ; shift velocity byte one to the right
OR BYTE ES:[BX],DL ; OR it in
MOV BYTE destbyte_,0 ; next byte will be a newmsg
ADD WORD ptr_,4 ; inr ptr
JMP _iret ; all done
_noff: ; note off processing routine
AND BL,1 ; BL still has destbyte in it
MOV WORD BX,ptr_ ; get pointer into buff
JZ _ntoffvel ; if destbyte=2, then it must be a velocity
ADD BX,3 ; inr to where we'll store the note
MOV BYTE ES:[BX],DL ; store note; top bit should already be 0
INC BYTE destbyte_ ; inr destbyte for velocity
JMP _iret ; all done
_ntoffvel: ; must be a velocity byte
SHR DL,1 ; shift DL logically right 1
OR BYTE ES:[BX],DL ; OR it in
MOV BYTE destbyte_,0 ; next byte will be a newmsg
ADD WORD ptr_,4 ; now _ptr points to the next message spot
JMP _iret ; all done
_pchan: ; program change (new program)
MOV WORD BX,ptr_ ; get pointer; no need to check byte number
; because only two bytes are transmitted
ADD BX,3 ; this is where we'll store the new prog. #
MOV BYTE ES:[BX],DL ; store data
MOV BYTE destbyte_,0 ; reset to newmsg
ADD WORD ptr_,4 ; inr to pstn. of next massage
JMP _iret ; all done
_bender: ; store bender data
AND BL,1 ; first data byte?
JZ _bmsb ; if not, than go and store the MSB
INC BYTE destbyte_ ; inr for next pass
JMP _iret ; all done
_bmsb: ; store MSB of bender
SHR DL,1 ; shift DL down 1
MOV WORD BX,ptr_ ; get ptr
OR BYTE ES:[BX],DL ; OR in top 6 of MSB of bender
ADD WORD ptr_,3 ; inr pointer to next message
MOV BYTE destbyte_,0 ; next message will newmsg
JMP _iret ; all done
_cchan: ; control change
AND BL,1 ; control #?
MOV WORD BX,ptr_ ; get ptr_
JNZ _cnum ; if input is control #, then save it
ADD BX,4 ; this is where we'll store the control value
MOV BYTE ES:[BX],DL ; store control value
MOV BYTE destbyte_,0 ; next byte will newmsg
ADD WORD ptr_,5 ; inr to next message location
JMP _iret ; all done
_cnum: ; number
ADD BX,3 ; address of control number
MOV BYTE ES:[BX],DL ; store control number
INC BYTE destbyte_ ; next byte will be control value
JMP _iret ; all done
_cvel: ; channel velocity
MOV WORD BX,ptr_ ; load BX w/pointer
MOV BYTE ES:[BX+3],DL ; store velocity
ADD WORD ptr_,4 ; inr to next message pstn.
MOV BYTE destbyte_,0 ; next byte will be new msg
JMP _iret ; all done
_keypres: ; poly. key pressure
AND BL,1 ; amount?
MOV WORD BX,ptr_
JZ _storepres ; store key pressure
ADD BX,3 ; this is where to store the note num.
MOV BYTE ES:[BX],DL ; store it
INC BYTE destbyte_ ; next byte will be val.
JMP _iret
_storepres: ; store key pressure
SHR DL,1
SHR DL,1 ; shift DL right 2 (/4)
OR ES:[BX],DL ; OR it in
MOV BYTE destbyte_,0 ; next byte new message
JMP _iret ; all done
_stime: ; routine to read the PIT and store the results
; in the buffer
PUSH DX ; preserve data
MOV WORD BX,ptr_ ; get pointer
MOV AL,clk_type_ ; get clk type (0=int)
OR AL,AL ; set flags
JNZ ext_clk ; is clk_type=ext_clk??
MOV AL,64 ; counter latching operation
MOV DX,0FFA7H ; counter stat
OUT DX,AL ; out to PIT
NOP ; stall for time
NOP
MOV DX,0FFA5H ; counter 2
IN AL,DX ; read _clsb
MOV BYTE ES:[BX+1],AL ; store in buffer
NOP
NOP
IN AL,DX ; read _cmsb
MOV BYTE ES:[BX+2],AL
POP DX ; restore data
RET
ext_clk: ; timing clock from MIDI
MOV DL,clsb_
MOV DH,cmsb_ ; get MSB & LSB
MOV BYTE ES:[BX+1],DL
MOV BYTE ES:[BX+2],DH ; store MSB & LSB
POP DX ; restore DX
RET ; all done
_eoi: ; send EOI to PIC
PUSH AX ; we'll be using this
MOV AL,020H ; EOI
OUT 020H,AL ; EOI
POP AX ; restore AX
RET ; all done
_iret1: ; execute EOI and then return
CALL _eoi
finished: ; Rx overrun error
MOV BYTE stop_,0FFH ; CRITICAL ERROR!!!
JMP f2
_iret: ; all done routine
MOV DX,0FFA2H ; DART status reg
IN AL,DX
AND AL,1 ; RxD? (THIS WILL HAVE TO BE CHANGED TO CHECK
; FOR EXTERNAL STAT. ALSO)
JNZ sst ; if so, than go to top of routine
f2: ; C equivalent:
; if(end > ptr)
; goto okay;
; else
; stop=1;
; MOV BX,ptr_
; MOV DX,end_
; CMP DX,BX
; JG f3
; MOV BYTE stop_,1 ; Woaaaah!! Stop Everything!! - We're out of memory
f3:
mov al,0b8h
out 021h,al
POP DS
POP ES
POP DX
POP BX
POP AX ; retrieve registers
call _eoi
IRET ; ALL DONE!!!!!!!